# build in python3.6.5
# author : hashaki
# 多线程练习

import threading
import time
# 使用threading创建线程
# 我们可以通过直接从 threading.Thread 继承创建一个新的子类，并实例化后调用 start() 方法启动新线程，即它调用了线程的 run() 方法：
class hashaki(threading.Thread):
    def __init__(self,threadID,name,counter):
        threading.Thread.__init__(self)
        self.threadID=threadID
        self.name=name
        self.counter=counter
    
    def run(self):
        print("线程开始 : ".join(self.name))
        printTime(self.name,self.counter,5)
        print("退出线程 ：".join(self.name))

def printTime(threadName,delay,counter):
    while counter:
        if False:
            threadName.exit()
        time.sleep(delay)
        print("{0}:{1}".format(threadName,time.ctime(time.time())))
        counter-=1
    
def partOne():
    # 创建新线程
    thread1=hashaki(1,"线程1",1)
    thread2=hashaki(2,"线程2",2)

    # 开启新线程
    thread1.start()
    thread2.start()
    thread1.join()
    thread2.join()
    print("完成hashaki")


########################################################
# 线程同步
class hashaki2(threading.Thread):
    def __init__(self,threadID,name,counter):
        threading.Thread.__init__(self)
        self.threadID=threadID
        self.name=name
        self.counter=counter
        self.Lock=threading.Lock()
        
    
    def run(self):
        print("开启线程".join(self.name))
        # 获取锁，用于线程同步
        self.Lock.acquire()
        printTime(self.name,self.counter,3)
        # 释放锁，开启下一个线程
        self.Lock.release()

def partTwo():
    
    threads=[]

    # 创建新线程
    thread1=hashaki(1,"线程1",1)
    thread2=hashaki(2,"线程2",2)

    # 开启新线程
    thread1.start()
    thread2.start()

    # 添加线程到线程列表
    threads.append(thread1)
    threads.append(thread2)

    for i in threads:
        i.join()
    print("搞定收工")

#####################################################################
# 优先队列
'''
Python 的 Queue 模块中提供了同步的、线程安全的队列类，包括FIFO（先入先出)队列Queue，LIFO（后入先出）队列LifoQueue，和优先级队列 PriorityQueue。

这些队列都实现了锁原语，能够在多线程中直接使用，可以使用队列来实现线程间的同步。

Queue 模块中的常用方法:

    Queue.qsize() 返回队列的大小
    Queue.empty() 如果队列为空，返回True,反之False
    Queue.full() 如果队列满了，返回True,反之False
    Queue.full 与 maxsize 大小对应
    Queue.get([block[, timeout]])获取队列，timeout等待时间
    Queue.get_nowait() 相当Queue.get(False)
    Queue.put(item) 写入队列，timeout等待时间
    Queue.put_nowait(item) 相当Queue.put(item, False)
    Queue.task_done() 在完成一项工作之后，Queue.task_done()函数向任务已经完成的队列发送一个信号
    Queue.join() 实际上意味着等到队列为空，再执行别的操作

'''
class hashaki3(threading.Thread):
    def __init__(self,threadID,name,q):
        threading.Thread.__init__(self)
        self.threadID=threadID
        self.name=name
        self.q=q

    def run(self):
        print("开启线程：".join(self.name))
        processData(self.name,self.q)
        print("结束进程:".join(self.name))

def processData(threadName,q):
    exitFlag = 0
    while not exitFlag:
        queueLock.acquire()
        if not workQueue.empty()
        data=q.get()
        queueLock.release()
        print("{0}进程{1}".format(threadName,data))
    else:
        queueLock.release()
    time.sleep(1)

queueLock = threading.Lock()
workQueue = queue.Queue(10)

def partThree():
    threadList = ["Thread-1", "Thread-2", "Thread-3"]
    nameList = ["One", "Two", "Three", "Four", "Five"]
    threads = []
    threadID = 1

    # 创建新线程
    for tName in threadList:
        thread = hashaki3(threadID, tName, workQueue)
        thread.start()
        threads.append(thread)
        threadID += 1

    # 填充队列
    queueLock.acquire()
    for word in nameList:
        workQueue.put(word)
    queueLock.release()

    # 等待队列清空
    while not workQueue.empty():
        pass

    # 等待所有线程完成
    for t in threads:
        t.join()
    print ("退出主线程")

if __name__=="__main__":
    #partOne()
    #partTwo()
    partThree()